package jmf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;

public class Grabadora extends Thread {
	private TargetDataLine line;

	private AudioFileFormat.Type targetType;

	private File file;

	private boolean grabando;
	
	private int nivelRuido;
	
	private double segundosDetectorSilencio;
	
	private int promedioGrabacion;
	
	private double contadorSilencios;

	public Grabadora(String archivo) {
		this.file = new File(archivo+".wav");
		AudioFormat audioFormat = new AudioFormat(
				AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 2, 4, 44100.0F,
				false);

		DataLine.Info info = new DataLine.Info(TargetDataLine.class,
				audioFormat);
		try {
			line = (TargetDataLine) AudioSystem.getLine(info);
			line.open(audioFormat);
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		}
		targetType = AudioFileFormat.Type.WAVE;
		line.start();
	}
	
	public void detener() {
		line.stop();
		line.drain();
		line.close();
		grabando = false;
	}

	public void run() {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
				
		capturarEnBuffer(byteArrayOutputStream);

		escribirBufferEnArchivo(byteArrayOutputStream);
	}

	private void capturarEnBuffer(ByteArrayOutputStream byteArrayOutputStream) {
		byte[] abBuffer = new byte[44000];//cuarto de segundo
		int suma= 0;
		contadorSilencios= 0;
		int sumaTotal=0;
		int contadorBuffer=0;
		
		grabando = true;
		while (grabando) {
			contadorBuffer++;
			int nFramesRead = line.read(abBuffer, 0, abBuffer.length);
			suma = 0;
			for (int i = 0; i < abBuffer.length;i++){
				suma += Math.abs(abBuffer[i]);
			}
			
			contadorSilencios = detectarSilencios(suma, contadorSilencios);
			
			byteArrayOutputStream.write(abBuffer, 0, nFramesRead);
			
			sumaTotal += suma;
			promedioGrabacion = sumaTotal/contadorBuffer;
		}

		try {
			byteArrayOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void escribirBufferEnArchivo(ByteArrayOutputStream byteArrayOutputStream) {
		AudioFormat format = line.getFormat();
		byte[] abData = byteArrayOutputStream.toByteArray();
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
				abData);
		
		AudioInputStream audioInputStream = new AudioInputStream(
				byteArrayInputStream, format, abData.length
				/ format.getFrameSize());
		try {
			AudioSystem.write(audioInputStream, targetType, file);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private double detectarSilencios(int suma, double contadorSilencios) {
		if(nivelRuido != 0 && segundosDetectorSilencio != 0){
			if (nivelRuido > 0 && suma <= nivelRuido){
				contadorSilencios++;
				if (segundosDetectorSilencio <= contadorSilencios/4){
					grabando = false;
				}
			}else{
				contadorSilencios = 0;
			}
		}
		return contadorSilencios;
	}

	public void setDetectorSilencios(int nivel, int segundos) {
		this.nivelRuido= nivel;
		this.segundosDetectorSilencio = segundos;
	}

	public int getPromedioGrabacion() {
		return promedioGrabacion;
	}

	public void setPromedioGrabacion(int promedioGrabacion) {
		this.promedioGrabacion = promedioGrabacion;
	}	
	
	public int obtenerPorcentajeDeteccion(){
		if (segundosDetectorSilencio > 0){
		double cantidadBuffers = segundosDetectorSilencio * 4;
		double porcentaje = contadorSilencios * 100 / cantidadBuffers;
		return new Double(porcentaje).intValue();
		}
		return 0;
	}
}
